import requests
import json
import gradio as gr

# 系统待处理任务数据 - 模拟银行零售贷款系统中需要处理的各类贷款审批任务
taskData = [
    {"id": "DK2023112001", "name": "个人住房贷款审批", "submitTime": "2023-11-20 14:30", "status": "待处理"},
    {"id": "DK2023112002", "name": "消费贷款审批", "submitTime": "2023-11-20 15:45", "status": "待处理"},
    {"id": "DK2023112003", "name": "经营贷款审批", "submitTime": "2023-11-20 16:20", "status": "待处理"},
]

# 逾期客户信息数据 - 模拟银行零售贷款系统中存在逾期情况的客户信息
overdueCustomerData = [
    {"name": "张明", "loanAmount": "¥500,000", "overdueDays": 35, "overdueAmount": "¥15,000"},
    {"name": "李婷", "loanAmount": "¥300,000", "overdueDays": 15, "overdueAmount": "¥8,000"},
]

# 系统消息提醒数据 - 模拟银行系统发送的各类通知信息
messageData = [
    {
        "id": 1,
        "title": "系统更新通知",
        "content": "系统将于今晚23:00-24:00进行例行维护更新",
        "time": "2023-11-20 10:00",
        "type": "system",
    },
    {
        "id": 2,
        "title": "风险预警提醒",
        "content": "客户张明贷款逾期超过30天，请及时处理",
        "time": "2023-11-20 09:30",
        "type": "warning",
    },
]

# 风险预警信息数据 - 模拟银行系统识别到的各类贷款风险预警
alertData = [
    {
        "id": 1,
        "title": "高风险预警",
        "content": "客户王建平近期出现多笔大额资金异常交易",
        "time": "2023-11-20 08:00",
        "level": "high",
    },
    {
        "id": 2,
        "title": "中风险预警",
        "content": "客户刘芳贷款即将到期，请提前通知",
        "time": "2023-11-19 16:30",
        "level": "medium",
    },
]


def convert_to_dataframe_format(data, keys):
    """将对象数组转换为Gradio Dataframe可显示的二维列表格式

    参数:
        data: 包含字典的列表，原始数据集合
        keys: 需要提取的字段列表，定义数据展示的顺序和内容

    返回:
        二维列表，每个子列表对应一条数据的指定字段值
    """
    return [[item[key] for key in keys] for item in data]


def export_data():
    """处理数据导出功能，返回导出成功提示信息"""
    return "数据已导出成功！"


chat_history = []  # 存储对话历史记录，格式为[(问题, 回答), ...]


def api_request(session_id, message):
    # 接口URL
    url = "http://localhost:8001/api/chat/send"

    # 请求头
    headers = {
        "Content-Type": "application/json"
    }

    # 请求体数据
    payload = {
        "message": message,
        "session_id": session_id
    }

    try:
        # 发送POST请求
        response = requests.post(
            url,
            headers=headers,
            data=json.dumps(payload),
            timeout=100
        )

        # 检查响应状态码
        if response.status_code == 200:
            print("[消息发送] ✅ 消息发送成功")
            return response.json()
        else:
            print(f"[消息发送] ❌ 接口返回错误状态码: {response.status_code}")
            print(f"[消息发送] 响应内容: {response.text}")
            return None

    except requests.exceptions.RequestException as e:
        print(f"[消息发送] ❌ 请求发生错误: {str(e)}")
        return None


def call_ai(question):
    """调用后端AI接口，处理对话逻辑并更新历史记录

    参数:
        question: 用户输入的问题

    返回:
        生成的回答和更新后的对话历史
    """
    # 验证输入问题是否为空
    if not question.strip():
        return chat_history

    # 构建包含历史对话的消息列表，用于上下文理解
    messages = []
    for q, a in chat_history:
        messages.append({"role": "user", "content": q})
        messages.append({"role": "assistant", "content": a})
    messages.append({"role": "user", "content": question})

    # 调用后端AI函数获取回答
    result = api_request(
        session_id="7fed0a8e-7503-4586-9750-07f98f249b2b",
        message=question
    )

    # 更新对话历史
    chat_history.append((question, result.get('response')))
    return chat_history


# 自定义CSS样式 - 用于美化界面元素，定义各类组件的外观和布局
custom_css = """
/* 全局样式设置 */
body {
    background-color: #f9fafb !important;
    font-family: 'Inter', system-ui, sans-serif;
    margin: 0;
    padding: 0;
}

/* 导航栏样式 */
.header-container {
    background-color: #0f4c81;
    color: white;
    padding: 1rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    box-sizing: border-box;
}

/* 标题和导航按钮容器 */
.title-nav-container {
    display: flex;
    align-items: center;
    gap: 2rem;
}

/* 系统标题样式 */
.app-title {
    font-size: 1.25rem;
    font-weight: bold;
    margin: 0;
    color: white !important;
}

/* 导航标签容器 */
.nav-tabs {
    display: flex;
    background-color: #0b3a5e;
    border-radius: 0.25rem 0.25rem 0 0;
    overflow: hidden;
    margin: 0;
}

/* 导航标签基础样式 */
.nav-tab {
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    color: white;
}

/* 激活状态的导航标签 */
.nav-tab.active {
    background-color: white;
    color: #0f4c81;
    font-weight: medium;
}

/* 搜索框容器 */
.search-container {
    display: flex;
    justify-content: center;
    flex: 1;
    padding: 0 1rem;
    margin: 0 1rem;
}

/* 搜索框样式 */
.search-input {
    background-color: #0b3a5e;
    border: 1px solid #082a46;
    border-radius: 0.375rem;
    padding: 0.5rem 0.5rem 0.5rem 2rem;
    color: white;
    font-size: 0.875rem;
    width: 100%;
    max-width: 25rem;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>');
    background-repeat: no-repeat;
    background-size: 16px;
    background-position: 0.75rem center;
}

/* 用户信息容器 */
.user-info-container {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-width: fit-content;
}

/* 用户信息样式 */
.user-info {
    display: flex;
    align-items: center;
}

/* 用户头像样式 */
.avatar {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    margin-right: 0.5rem;
}

/* 用户名样式 */
.user-name {
    font-size: 0.875rem;
    margin-right: 0.5rem;
    color: white !important;
}

/* 主内容区域布局 */
.main-content {
    padding: 1rem;
    display: flex;
    gap: 1rem;
    width: 100%;
    box-sizing: border-box;
}

/* 卡片容器样式 */
.card {
    background: white;
    border-radius: 0.5rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    margin-bottom: 1rem;
    overflow: hidden;
}

/* 卡片头部样式 */
.card-header {
    padding: 0.5rem;
    border-bottom: 1px solid #e5e7eb;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* 卡片标题样式 */
.card-title {
    font-size: 1rem;
    font-weight: medium;
    color: #111827;
    margin: 0;
}

/* 按钮样式 */
.btn {
    background-color: #0f4c81;
    color: white;
    border: none;
    border-radius: 0.375rem;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* 按钮图标样式 */
.btn i {
    color: white !important;
}

/* 数据表格容器 */
.dataframe-container {
    padding: 0 1rem 1rem;
}

/* 数据表格样式 */
.dataframe {
    width: 100% !important;
    border-collapse: collapse;
    font-size: 0.875rem;
}

/* 表格头部样式 */
.dataframe th {
    background-color: #f9fafb;
    color: #6b7280;
    text-align: left;
    padding: 0.75rem;
    border-bottom: 1px solid #e5e7eb;
}

/* 表格单元格样式 */
.dataframe td {
    padding: 0.75rem;
    border-bottom: 1px solid #e5e7eb;
}

/* 列表容器样式 */
.list-container {
    padding: 0.75rem;
}

/* 消息卡片样式 */
.msg-card {
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.75rem;
    background-color: #f9fafb;
    margin-bottom: 0.75rem;
    display: flex;
}

/* 消息图标样式 */
.msg-icon {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 0.75rem;
    margin-top: 0.25rem;
}

/* 系统消息图标样式 */
.msg-system {
    background-color: #fef3c7;
    color: #d97706;
}

/* 警告消息图标样式 */
.msg-warning {
    background-color: #fee2e2;
    color: #b91c1c;
}

/* 消息标题样式 */
.msg-title {
    font-size: 0.875rem;
    font-weight: medium;
    margin-bottom: 0.25rem;
}

/* 消息内容样式 */
.msg-desc {
    font-size: 0.75rem;
    color: #4b5563;
    margin-bottom: 0.25rem;
}

/* 消息时间样式 */
.msg-time {
    font-size: 0.7rem;
    color: #6b7280;
}

/* 感叹号图标样式 */
.exclamation-icon {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background-color: #0f4c81;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    margin-right: 0.5rem;
}

/* 感叹号图标颜色 */
.exclamation-icon i {
    color: white !important;
}

/* 导出按钮容器 */
.export-btn-container {
    display: flex;
    justify-content: flex-end;
    width: 100%;
}

/* AI对话按钮样式 */
#ai-button {
    position: fixed !important;
    bottom: 2rem;
    right: 2rem;
    width: 4rem !important;
    height: 4rem !important;
    border-radius: 50% !important;
    background-color: #0f4c81 !important;
    color: white !important;
    border: none !important;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 1.8rem !important;
    z-index: 100 !important;
    transition: all 0.2s ease !important;
    padding: 0 !important;
    min-width: auto !important;
}

#ai-button:hover {
    background-color: #0b3a5e !important;
    transform: scale(1.05) !important;
}

/* AI对话模态框样式 */
.ai-modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 1000;
    align-items: center;
    justify-content: center;
}

.ai-modal-content {
    background-color: white;
    width: 90%;
    max-width: 600px;
    border-radius: 0.5rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    overflow: hidden;
}

/* 模态框头部样式 - 控制关闭按钮位置 */
.ai-modal-header {
    padding: 1rem;
    background-color: #0f4c81;
    color: white;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* AI助手标题样式 - 设置为白色 */
.ai-modal-header h3 {
    color: white !important;
    margin: 0;
}

/* 小尺寸关闭按钮样式 */
.ai-modal-header .btn {
    padding: 0.3rem 0.6rem;
    font-size: 1rem;
}

.ai-modal-body {
    padding: 1rem;
}
"""

# 创建Gradio应用界面，设置CSS样式和页面标题
with gr.Blocks(css=custom_css, title="XX银行零售贷款系统") as demo:
    # 创建状态组件用于显示操作结果（隐藏状态，不直接显示在界面上）
    export_status = gr.Textbox(label="操作状态", visible=False)

    # 引入Font Awesome图标库，用于界面中的各类图标展示
    gr.HTML("""
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    """)

    # 导航栏区域 - 包含系统标题、导航标签、搜索框和用户信息
    with gr.Row(elem_classes="header-container"):
        with gr.Column(scale=3, elem_classes="title-column"):
            gr.Markdown("""
                <div class='title-nav-container'>
                    <h1 class='app-title'>XX银行零售贷款系统</h1>
                    <div class='nav-tabs'>
                        <div class='nav-tab active'>首页 <span class='ml-1'>×</span></div>
                        <div class='nav-tab'>贷款申请 <span class='ml-1'>×</span></div>
                    </div>
                </div>
            """)

        with gr.Column(scale=4, elem_classes="search-container"):
            # 搜索框组件，用于搜索系统功能或内容
            gr.Markdown("""
                <input type='text' placeholder='搜索菜单' class='search-input'>
            """)

        with gr.Column(scale=2, elem_classes="user-info-container"):
            # 用户信息展示区域，包含头像和用户名
            gr.Markdown("""
                <div class='user-info'>
                    <img src='https://space.coze.cn/api/coze_space/gen_image?image_size=square&prompt=bank%20employee%20avatar%2C%20male%2C%20professional%20looking&sign=1869ec47c7bc9cbd26b803e32bec4a31' 
                         alt='用户头像' class='avatar'>
                    <span class='user-name'>测试用户</span>
                    <i class='fa-solid fa-chevron-down' style='color: white; font-size: 0.75rem;'></i>
                </div>
            """)

    # 主内容区域 - 分为左右两栏展示不同内容
    with gr.Row(elem_classes="main-content"):
        # 左侧主内容区（占比7/12）
        with gr.Column(scale=7):
            # 待办任务卡片
            with gr.Column(elem_classes="card"):
                with gr.Row(elem_classes="card-header"):
                    # 卡片标题，显示"我的待办"和"我的已办"标签
                    gr.Markdown(
                        "<h2 class='card-title' style='color: #0f4c81; border-bottom: 2px solid #0f4c81; padding-bottom: 0.5rem;'>我的待办 (12)</h2>")
                    gr.Markdown(
                        "<h2 class='card-title' style='color: #6b7280; padding-bottom: 0.5rem;'>我的已办 (156)</h2>")

                with gr.Column(elem_classes="dataframe-container"):
                    # 待办任务表格，展示任务编号、名称、提交时间和状态
                    gr.Dataframe(
                        value=convert_to_dataframe_format(taskData, ["id", "name", "submitTime", "status"]),
                        headers=["业务编号", "任务名称", "提交时间", "状态"],
                        elem_classes="dataframe",
                        interactive=False
                    )

            # 逾期客户信息卡片
            with gr.Column(elem_classes="card"):
                with gr.Row(elem_classes="card-header"):
                    with gr.Column(scale=8):
                        # 卡片标题，显示"逾期客户信息"
                        gr.Markdown("""
                            <h2 class='card-title'>
                                <span class='exclamation-icon'><i class='fa-solid fa-exclamation-circle'></i></span>
                                逾期客户信息
                            </h2>
                        """)

                    with gr.Column(scale=2, elem_classes="export-btn-container"):
                        # 隐藏的导出按钮（用于功能绑定）
                        hidden_export_btn = gr.Button("导出数据", visible=False)
                        # 自定义导出按钮HTML
                        gr.HTML("""
                            <button id="export-button" class="btn">
                                <i class='fa-solid fa-download'></i> 导出数据
                            </button>
                        """)
                        # JavaScript代码用于将自定义按钮点击事件绑定到隐藏的Gradio按钮
                        gr.HTML("""
                            <script>
                                document.addEventListener('DOMContentLoaded', function() {
                                    const htmlBtn = document.getElementById('export-button');
                                    const gradioBtns = document.querySelectorAll('.gr-button');
                                    let gradioBtn = null;

                                    for (let btn of gradioBtns) {
                                        if (btn.textContent.trim() === '导出数据') {
                                            gradioBtn = btn;
                                            break;
                                        }
                                    }

                                    if (htmlBtn && gradioBtn) {
                                        htmlBtn.addEventListener('click', function() {
                                            gradioBtn.click();
                                        });
                                    }
                                });
                            </script>
                        """)
                        # 绑定导出按钮事件，点击后执行数据导出功能
                        hidden_export_btn.click(
                            fn=export_data,
                            outputs=[export_status]
                        )

                with gr.Column(elem_classes="dataframe-container"):
                    # 逾期客户信息表格，展示客户姓名、贷款金额、逾期天数和逾期金额
                    gr.Dataframe(
                        value=convert_to_dataframe_format(overdueCustomerData,
                                                          ["name", "loanAmount", "overdueDays", "overdueAmount"]),
                        headers=["客户姓名", "贷款金额", "逾期天数", "逾期金额"],
                        elem_classes="dataframe",
                        interactive=False
                    )

        # 右侧边栏区域（占比5/12）
        with gr.Column(scale=5):
            # 消息提醒卡片
            with gr.Column(elem_classes="card"):
                with gr.Row(elem_classes="card-header"):
                    # 卡片标题和"查看更多"链接
                    gr.Markdown("<h2 class='card-title'>消息提醒</h2>")
                    gr.Markdown(
                        "<a href='#' style='color: #0f4c81; font-size: 0.875rem; text-decoration: none;'>查看更多</a>")

                with gr.Column(elem_classes="list-container"):
                    # 循环展示消息提醒数据
                    for msg in messageData:
                        # 根据消息类型设置不同的图标样式
                        icon_cls = "msg-system" if msg["type"] == "system" else "msg-warning"
                        icon_text = "⚠" if msg["type"] == "system" else "🔴"
                        gr.Markdown(f"""
                            <div class='msg-card'>
                                <div class='msg-icon {icon_cls}'>{icon_text}</div>
                                <div>
                                    <div class='msg-title'>{msg['title']}</div>
                                    <div class='msg-desc'>{msg['content']}</div>
                                    <div class='msg-time'>{msg['time']}</div>
                                </div>
                            </div>
                        """)

            # 预警信息卡片
            with gr.Column(elem_classes="card"):
                with gr.Row(elem_classes="card-header"):
                    # 卡片标题
                    gr.Markdown("<h2 class='card-title'>预警信息</h2>")

                with gr.Column(elem_classes="list-container"):
                    # 循环展示风险预警信息
                    for alert in alertData:
                        # 根据风险级别设置不同的图标样式
                        icon_cls = "msg-warning" if alert["level"] == "high" else "msg-system"
                        icon_text = "🔴" if alert["level"] == "high" else "⚠"
                        gr.Markdown(f"""
                            <div class='msg-card'>
                                <div class='msg-icon {icon_cls}'>{icon_text}</div>
                                <div>
                                    <div class='msg-title'>{alert['title']}</div>
                                    <div class='msg-desc'>{alert['content']}</div>
                                    <div class='msg-time'>{alert['time']}</div>
                                </div>
                            </div>
                        """)

    # AI对话功能模块 - 模态框形式展示
    with gr.Column(elem_classes="ai-modal", visible=False) as ai_modal:
        with gr.Column(elem_classes="ai-modal-content"):
            with gr.Row(elem_classes="ai-modal-header"):
                # 模态框标题
                gr.Markdown("<h3>AI助手</h3>")
                # 关闭按钮
                close_btn = gr.Button("关闭", elem_classes="btn")

            with gr.Column():
                # 对话历史展示区域
                chat_display = gr.Chatbot(label="对话历史", height=400)
                # 问题输入区域
                question = gr.Textbox(label="请输入问题", lines=4)
                # 发送按钮
                submit_btn = gr.Button("发送", elem_classes="btn")

            # 绑定发送按钮事件，点击后调用AI接口
            submit_btn.click(
                fn=call_ai,
                inputs=[question],
                outputs=[chat_display]
            )
            # 绑定回车键事件，输入问题后按回车也能发送
            question.submit(
                fn=call_ai,
                inputs=[question],
                outputs=[chat_display]
            )

            # 绑定关闭按钮事件，点击后隐藏模态框
            close_btn.click(
                fn=lambda: gr.update(visible=False),
                outputs=ai_modal
            )

    # AI助手按钮 - 固定在页面右下角
    ai_button = gr.Button("🤖", elem_id="ai-button")
    # 绑定AI按钮事件，点击后显示AI对话模态框
    ai_button.click(
        fn=lambda: gr.update(visible=True),
        outputs=ai_modal
    )

# 应用入口，启动Gradio服务
if __name__ == "__main__":
    demo.launch(debug=True)
